package controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import persistence.ProductoMapper;
import persistence.ProveedorMapper;
import view.FacturaPanel;
import model.Factura;
import model.Material;
import model.OrdenDeCompra;
import model.Producto;
import model.Proveedor;


public class MainController {
	public static final int ORDEN_GENERADA = 1;
	public static final int ORDEN_NO_GENERADA = 0;
	public static final int ORDEN_ERROR = -1;
	private List<Proveedor> proveedores;
	private List<Factura> facturas;
	private List<OrdenDeCompra> ordenesDeCompra;
	private boolean fullyLoadedProv = false;
	private ProductoMapper productoMapper;
	private FacturaPanel facturaPanel;

	private static MainController instance = null;
	
	
	private MainController(){
		proveedores = new ArrayList<Proveedor>();
		facturas = new ArrayList<Factura>();
		ordenesDeCompra = new ArrayList<OrdenDeCompra>();
	}	
	
	public static MainController getInstance() {
		if(instance == null){
			instance = new MainController(); 
		}
		
		return instance;
	}
	
	/**
	 * Alta de un nuevo proveedor en el sistema. El codigo es unico, por lo tanto no debe existir ya un proveedor con el mismo codigo.
	 * @param codigo codigo que representa univocamente al proveedor
	 * @param nombre nombre del proveedor
	 * @return <b>true</b> en caso de que el alta haya sido efectiva, <b>false</b> si ya existia un proveedor con el mismo codigo
	 */
	public boolean altaProveedor(String codigo, String nombre) {
		boolean result = false;
		if(buscarProveedor(codigo) == null){
			Proveedor altaProveedor = new Proveedor(codigo);
			result = altaProveedor.guardar();
			proveedores.add(altaProveedor);
		}
		return result;
	}
	
	/**
	 * Busqueda de un proveedor con el codigo recibido.
	 * @param codigo codigo del proveedor a buscar
	 * @return <b>null</b> en caso de que no exista un proveedor con el codigo recibido, el Proveedor correspondiente al codigo buscado
	 */
	public Proveedor buscarProveedor(String codigo){
		Proveedor result = null;
		
		for(Proveedor proveedor: getProveedores()) {
			if(proveedor.hasCodigo(codigo)){
				result = proveedor;
				break;
			}
		}
		return result;
	}

	public List<Proveedor> getProveedores() {
		if(!fullyLoadedProv) {
			proveedores = ProveedorMapper.getInstance().buscarTodos();
			fullyLoadedProv = true;
		}
		return proveedores;
	}

		
	
	
	/**
	 * Se generan ordenes de compra para los materiales cuyo stock este por debajo del punto de pedido. 
	 * @return <b>true</b> si se genero al menos una orden de compra, <b>false</b> si no habia materiales debajo del punto de pedido
	 */
	public int generarOrdenesDeCompra() {
		int generaOrdenes = ORDEN_NO_GENERADA;
		for(Proveedor proveedor: getProveedores()) {
			boolean provAComprar = false;
			OrdenDeCompra ordenCompra = new OrdenDeCompra(proveedor);
			for(Material material: proveedor.getMateriales()) {
				if(material.necesitaReponer()) {
					provAComprar = true;
					ordenCompra.agregarMaterial(material, material.getCantidadAReponer());
				}
			}
			
			if(provAComprar) {
				ordenCompra.calcularMonto();
				boolean ordenGuardada = ordenCompra.guardar();
				generaOrdenes = (ordenGuardada)? ORDEN_GENERADA: ORDEN_ERROR;
				if(generaOrdenes == ORDEN_ERROR) return generaOrdenes;
				ordenesDeCompra.add(ordenCompra);
			}
		}
		
		return generaOrdenes;
	}
	
	/**
	 * Recibimos un map con los productos vendidos como clave y la cantidad vendida como valor.
	 * @param productos
	 * @return
	 */
	public boolean altaFactura(Map<Producto, Integer> productos) {
		Factura factura = new Factura(productos);
		boolean result = factura.guardar();
		facturas.add(factura);
		return result;
	}
	
	public void altaFacturaPanel() {
		productoMapper = ProductoMapper.getInstance();
		facturaPanel = new FacturaPanel(productoMapper.buscarProductos());
		facturaPanel.showPanel();
	}
}
		
